# -*- coding: utf8 -*-
#
# Copyright (c) 2009 Matías Ribecky <mail@mribecky.com.ar>
#
# This file is part of twitter-notifications.
# 
# twitter-notifications is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# twitter-notifications is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with twitter-notifications.  If not, see <http://www.gnu.org/licenses/>.

'''Has the different implementations for the notifiers.'''

import logging
import threading

import pynotify
import gobject

pynotify.init('twitter-notification')

LOGGER = logging.getLogger('twitternotifications.main')

class Notifier(object):
    '''Abstract base class for the notifiers.'''

    name = None
    options = {}

    @classmethod
    def plugin_list(cls):
        '''Return a set of the plugin names.'''

        plugin_list = set()
        for sub_cls in cls.__subclasses__():
            plugin_list |= sub_cls.plugin_list()

        if cls.name:
            plugin_list.add(cls.name)

        return plugin_list

    @classmethod
    def get_plugin(cls, name):
        '''Get a plugin by name.'''
        if cls.name == name:
            return cls
        else:
            for sub_cls in cls.__subclasses__():
                found = sub_cls.get_plugin(name)
                if found:
                    return found
            return None

    def notify(self, status):
        '''Notify of the status.'''

        LOGGER.info("%s notifier: notifying of status %s" %
                    (self.name, status.id))

    def __init__(self, config):
        '''Create a notifier.'''

        self.config = config

class LibNotifyNotifier(Notifier):
    '''Libnotify implementation.'''

    name = 'libnotify'

    def __init__(self, config):
        '''Create a notifier.'''

        Notifier.__init__(self, config)
        self._gobject_main_thread = GobjectMainThread()
        self._gobject_main_thread.setDaemon(True)
        self._gobject_main_thread.start()

        self.seq = NotificationsSequencer()

    def notify(self, status):
        '''Notify of the status.'''

        Notifier.notify(self, status)

        title = "Twitter: " + status.user.user_name
        msg = status.message
        image = 'file://' + status.user.image
        notif = pynotify.Notification(title.encode('utf8'), msg.encode('utf8'),
                                      image)
        notif.set_urgency(pynotify.URGENCY_LOW)
        if self.config['timeout']:
            notif.set_timeout(self.config['timeout'] * 1000)
        else:
            notif.set_timeout(pynotify.EXPIRES_NEVER)

        for i in range(self.config['times']):
            self.seq.show(notif)

class NotificationsSequencer(object):
    '''Shows notifications in a sequence.'''

    def __init__(self):
        self.queue = []

    def show(self, notification):
        '''Show or enqueue if theres already a notification being shown.'''

        self.queue.append(notification)
        if len(self.queue) == 1:
            LOGGER.debug("Showing notification %s" % notification)
            notification.connect('closed', self.on_close)
            notification.show()

    def on_close(self, notification):
        '''Remove the notification being shown and show the next one.'''

        last_notification = self.queue.pop(0)
        LOGGER.debug("Notification %s was closed" % last_notification)
        assert last_notification == notification

        if self.queue:
            LOGGER.debug("Showing notification %s" % self.queue[0])
            self.queue[0].connect('closed', self.on_close)
            self.queue[0].show()

gobject.threads_init()
class GobjectMainThread(threading.Thread):
    def run(self):
        loop = gobject.MainLoop()
        loop.run()

class StdoutNotifier(Notifier):
    '''Output to stdout implementation.'''

    name = 'stdout'

    def notify(self, status):
        '''Notify of the status.'''

        Notifier.notify(self, status)

        print status.user.user_name
        print '    ' + status.message
